package com.isoftstone.service.impl;

import com.isoftstone.mapper.DormitoryMapper;
import com.isoftstone.mapper.OccupancyMapper;
import com.isoftstone.mapper.StudentMapper;
import com.isoftstone.pojo.Dormitory;
import com.isoftstone.pojo.Occupancy;
import com.isoftstone.pojo.PageResult;
import com.isoftstone.pojo.Student;
import com.isoftstone.pojo.dto.AssignDormitoryDTO;
import com.isoftstone.pojo.dto.OccupancyQueryDTO;
import com.isoftstone.service.OccupancyService;

import com.isoftstone.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author :W.
 * @Date:2025/9/16 16:42
 */
@Service
public class OccupancyServiceImpl implements OccupancyService {
    @Autowired
    private OccupancyMapper occupancyMapper;

    @Autowired
    private DormitoryMapper dormitoryMapper;

    @Autowired
    private StudentMapper studentMapper;  // 假设存在该Mapper
    // 多条件查询入住记录
    @Override
    public Result<PageResult<Occupancy>> queryByConditions(OccupancyQueryDTO queryDTO) {
        // 1. 处理默认分页参数（避免null）
        if (queryDTO.getCurrentPage() == null) queryDTO.setCurrentPage(1);
        if (queryDTO.getPageSize() == null) queryDTO.setPageSize(10);

        // 2. 查询分页数据列表
        List<Occupancy> list = occupancyMapper.queryByConditions(queryDTO);
        // 3. 查询符合条件的总记录数
        Integer total = occupancyMapper.countByConditions(queryDTO);

        // 4. 封装分页结果
        PageResult<Occupancy> pageResult = new PageResult<>();
        pageResult.setList(list);
        pageResult.setTotal(total);
        pageResult.setCurrentPage(queryDTO.getCurrentPage());
        pageResult.setPageSize(queryDTO.getPageSize());

        return Result.success(pageResult);
    }

    // 分配宿舍
    @Override
    @Transactional
    public Result<?> assignDormitory(AssignDormitoryDTO dto) {
        // 1. 校验学生是否存在
        Student student = studentMapper.findByStudentNumber(dto.getStudentNumber());
        if (student == null) {
            return Result.error("学生不存在");
        }

        // 2. 校验学生是否已入住
        Occupancy currentOccupancy = occupancyMapper.findCurrentByStudentNumber(dto.getStudentNumber());
        if (currentOccupancy != null) {
            return Result.error("该学生已入住，不能重复分配");
        }

        // 3. 查找指定的宿舍
        Dormitory dormitory = dormitoryMapper.findByBuildingAndRoom(dto.getBuildingNumber(), dto.getRoomNumber());
        if (dormitory == null) {
            return Result.error("指定的宿舍不存在");
        }

        // 4. 检查宿舍是否有空位
        int currentOccupancyCount = occupancyMapper.countByDormitoryId(dormitory.getDormitoryId());
        if (currentOccupancyCount >= dormitory.getCapacity()) {
            return Result.error("该宿舍已满，无法分配");
        }

        // 5. 创建入住记录
        Occupancy occupancy = new Occupancy();
        occupancy.setStudentId(student.getId());
        occupancy.setStudentNumber(student.getStudentNumber());
        occupancy.setDormitoryId(dormitory.getDormitoryId());

        // 6. 保存入住记录
        int rows = occupancyMapper.addOccupancy(occupancy);
        if (rows <= 0) {
            return Result.error("分配宿舍失败");
        }
        // 7. 更新宿舍当前入住人数
        dormitoryMapper.updateOccupancy(dormitory.getDormitoryId(),  1);
        return Result.success("分配宿舍成功");
    }

    // 调换宿舍
    @Override
    @Transactional
    public Result<?> changeDormitory(AssignDormitoryDTO dto) {
        // ----------------------------------------------------------------
        // 1. 校验学生是否存在
        Student student = studentMapper.findByStudentNumber(dto.getStudentNumber());
        if (student == null) {
            return Result.error("学生不存在");
        }

        // 2. 校验学生是否已入住
        Occupancy currentOccupancy = occupancyMapper.findCurrentByStudentNumber(dto.getStudentNumber());
        if (currentOccupancy == null) {
            return Result.error("该学生未入住，无法调换宿舍");
        }

        // 3. 查找目标宿舍
        Dormitory targetDorm = dormitoryMapper.findByBuildingAndRoom(dto.getBuildingNumber(), dto.getRoomNumber());
        if (targetDorm == null) {
            return Result.error("目标宿舍不存在");
        }

        // 4. 检查目标宿舍是否有空位
        int targetOccupancyCount = occupancyMapper.countByDormitoryId(targetDorm.getDormitoryId());
        if (targetOccupancyCount >= targetDorm.getCapacity()) {
            return Result.error("目标宿舍已满，无法调换");
        }

        // 2. 核心更新逻辑（简化为3步）
        Integer sourceDormId = currentOccupancy.getDormitoryId();
        Integer targetDormId = targetDorm.getDormitoryId();

        // 2.1 更新入住记录（直接修改，无外键冲突）
        currentOccupancy.setDormitoryId(targetDormId);
        if (occupancyMapper.updateOccupancy(currentOccupancy) <= 0) {
            return Result.error("更新入住记录失败");
        }

        // 2.2 更新学生表（直接关联宿舍表，无冲突）
        if (studentMapper.updateDormitoryInfo(dto.getStudentNumber(), targetDormId,
                targetDorm.getBuildingNumber() + "-" + targetDorm.getRoomNumber()) <= 0) {
            return Result.error("更新学生宿舍信息失败");
        }

        // 2.3 更新宿舍人数
        dormitoryMapper.updateOccupancy(sourceDormId, -1);
        dormitoryMapper.updateOccupancy(targetDormId, +1);

        return Result.success("调换宿舍成功");
    }

    // 单个退宿
    // 单个退宿（完整修复版）
    @Override
    @Transactional  // 确保所有操作在同一事务，要么全成功，要么全回滚
    public Result<?> checkOut(Integer occupancyId) {
        // 1. 校验入住记录ID是否存在
        if (occupancyId == null) {
            return Result.error("入住记录ID不能为空");
        }
        // 2. 查询入住记录（必须在更新前查询，否则状态已改，校验失效）
        Occupancy occupancy = occupancyMapper.findById(occupancyId);
        if (occupancy == null) {
            return Result.error("入住记录不存在");
        }
        // 3. 校验是否已退宿（状态0=退宿，1=在住）
        if (occupancy.getStatus() == 0) {
            return Result.error("该学生已退宿，无需重复操作");
        }
        // 4. 执行退宿：更新入住记录状态为“退宿”
        int rows = occupancyMapper.checkOut(occupancyId);
        if (rows <= 0) {
            return Result.error("退宿失败");
        }
        // 5. 核心修复：清空学生表的宿舍关联信息（关键步骤）
        // 注意：根据数据库字段约束选择传 null 或空字符串 ""
        // 如果数据库允许 dormitory_id 为 null，传 null；否则传 0（需确保数据库字段允许）
        // dormitory 字段传空字符串 ""（通常字符串字段允许空）
        studentMapper.updateDormitoryInfo(
                occupancy.getStudentNumber(),  // 学生学号
                null,  // 清空 dormitory_id（若数据库不允许null，改为 0 或 ""，需同步修改Mapper）
                ""     // 清空 dormitory 字段（宿舍信息字符串）
        );
        // 6. 修复：更新宿舍入住人数（传递“变化量 -1”，表示减少1人）
        Integer dormId = occupancy.getDormitoryId();
        if (dormId != null) {
            // 调用 updateOccupancy 方法，参数为“宿舍ID”和“人数变化量”
            dormitoryMapper.updateOccupancy(dormId, -1);
        }
        return Result.success("退宿成功");
    }
    @Override
    @Transactional
    public Result<?> batchCheckOut(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return Result.error("请选择要退宿的记录");
        }

        // 步骤1：先查询所有选中记录中“在住”（status=1）的记录，保存到列表中
        List<Occupancy> validOccupancies = new ArrayList<>();
        for (Integer id : ids) {
            Occupancy occupancy = occupancyMapper.findById(id);
            if (occupancy != null && occupancy.getStatus() == 1) { // 只保留在住的记录
                validOccupancies.add(occupancy);
            }
        }
        if (validOccupancies.isEmpty()) {
            return Result.error("所选记录中无“在住”状态的学生");
        }

        // 步骤2：批量更新这些“在住”记录的status为0（退宿）
        List<Integer> validIds = validOccupancies.stream()
                .map(Occupancy::getOccupancyId)
                .collect(Collectors.toList());
        int rows = occupancyMapper.batchCheckOut(validIds);
        if (rows <= 0) {
            return Result.error("批量退宿失败");
        }

        // 步骤3：基于保存的validOccupancies，执行核心逻辑（不会被跳过）
        for (Occupancy occupancy : validOccupancies) {
            // 3.1 清空学生表的宿舍信息（解决“已入住”提示问题）
            studentMapper.updateDormitoryInfo(
                    occupancy.getStudentNumber(),
                    null,          // 清空dormitory_id
                    ""             // 清空dormitory字符串
            );

            // 3.2 更新宿舍人数（退宿减少1人，解决人数未减少问题）
            Integer dormId = occupancy.getDormitoryId();
            if (dormId != null) {
                dormitoryMapper.updateOccupancy(dormId, -1); // 传递变化量-1
            }
        }

        return Result.success("成功退宿" + rows + "条记录");
    }


    // 获取学生入住信息列表
    @Override
    public Result<List<Occupancy>> getOccupancyList() {
        OccupancyQueryDTO queryDTO = new OccupancyQueryDTO();
        List<Occupancy> list = occupancyMapper.queryByConditions(queryDTO);
        return Result.success(list);
    }
    @Override
    @Transactional
    public Result<?> deleteRecords(List<Integer> ids) {
        if (ids == null || ids.isEmpty()) {
            return Result.error("请选择要删除的记录");
        }
        // 1. 只允许删除“已退宿”的记录（status = 0）
        int count = occupancyMapper.countByIdsAndStatus(ids, 0);
        if (count != ids.size()) {
            return Result.error("只能删除“已退宿”的记录");
        }
        // 2. 删除
        int rows = occupancyMapper.deleteByIds(ids);
        return rows > 0 ? Result.success("删除成功") : Result.error("删除失败");
    }

    @Override
    public Result<?> checkCurrentOccupancy(String studentNumber) {
        // 实现逻辑：查询学生当前是否在住
        Occupancy currentOccupancy = occupancyMapper.findCurrentByStudentNumber(studentNumber);
        if (currentOccupancy != null) {
            // 若在住，返回宿舍信息
            return Result.success(currentOccupancy);
        } else {
            return Result.success(null); // 未在住返回 null
        }
    }
}